/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef ProgramStateCache_h__
#define ProgramStateCache_h__

#include "../base/common.h"
#include "../utility/Singleton.h"
#include "../utility/MacroTool.h"

namespace SkyEngine2d
{
	
	class ProgramStateCache;
	class DepthStencilState
	{
	public:
		ID3D11DepthStencilState*  DepthNone() const;
		ID3D11DepthStencilState*  DepthDefault() const;
		ID3D11DepthStencilState*  DepthRead() const;
	
	private:
		ProgramStateCache * m_programStateCache;
	
		FRIEND_CLASS(ProgramStateCache);
	};
	
	class RasterizerState
	{
	public:
		ID3D11RasterizerState*  CullNone() const;
		ID3D11RasterizerState*  CullClockwise() const;
		ID3D11RasterizerState*  CullCounterClockwise() const;
		ID3D11RasterizerState*  Wireframe() const;
	private:
		ProgramStateCache * m_programStateCache;
		FRIEND_CLASS(ProgramStateCache);
	};
	
	class SamplerState
	{
	public:
		ID3D11SamplerState*  PointWrap() const;
		ID3D11SamplerState*  PointClamp() const;
		ID3D11SamplerState*  LinearWrap() const;
		ID3D11SamplerState*  LinearClamp() const;
		ID3D11SamplerState*  AnisotropicWrap() const;
		ID3D11SamplerState*  AnisotropicClamp() const;
	
	private:
		ProgramStateCache * m_programStateCache;
		FRIEND_CLASS(ProgramStateCache);
	};
	
	class BlendState
	{
	public:
		ID3D11BlendState* Opaque() const;
		ID3D11BlendState* AlphaBlend() const;
		ID3D11BlendState* Additive() const;
		ID3D11BlendState* NonPremultiplied() const;
	
	private:
		ProgramStateCache * m_programStateCache;
		FRIEND_CLASS(ProgramStateCache);
	};
	
	class ProgramStateCache
		:public Singleton<ProgramStateCache>
	{
		SINGLETON_CLASS(ProgramStateCache);
	public:
	
		BlendState * getBlendState()const { return m_blendState.get(); };
		DepthStencilState * getDepthStencilState()const { return m_depthStencilState.get(); }
		RasterizerState* getRasterizerState()const { return m_rasterizerState.get(); }
		SamplerState * getSamplerState()const { return m_samplerState.get(); }
	private:
		ProgramStateCache();
		~ProgramStateCache() {}
	private:
		std::unique_ptr<BlendState> m_blendState;
		std::unique_ptr<DepthStencilState> m_depthStencilState;
		std::unique_ptr<RasterizerState> m_rasterizerState;
		std::unique_ptr<SamplerState> m_samplerState;
	
		FRIEND_CLASS(BlendState);
		FRIEND_CLASS(DepthStencilState);
		FRIEND_CLASS(RasterizerState);
		FRIEND_CLASS(SamplerState);
	private:
		ID3D11Device * m_device;
	};
}

#endif // ProgramStateCache_h__
